﻿using System;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Input;
using Hardcodet.Wpf.TaskbarNotification;
using LokumClient.Models;
using LokumClient.ViewModels;
using Microsoft.Win32;

namespace LokumClient.Views
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly WebClient _webClient;
        private readonly MainViewModel _viewModel;
        private Timer _timer;

        public MainWindow(int updateInterval)
        {
            InitializeComponent();

            _viewModel = new MainViewModel(ShowHideApp);
            MainGrid.DataContext = _viewModel;

            _webClient = new WebClient();

            InitTimer(updateInterval);

            SystemEvents.SessionSwitch += OnSessionSwitch;
        }

        private void InitTimer(int updateInterval)
        {
            _timer = new Timer
            {
                Interval = TimeSpan.FromHours(updateInterval).TotalMilliseconds
            };
            _timer.Elapsed += OnTimerElapsed;
            _timer.Start();
        }

        public void TimerDispose()
        {
            _timer.Stop();
            _timer.Elapsed -= OnTimerElapsed;
            _timer?.Dispose();
        }

        public void ShowNotification()
        {
            NotifyIcon.ShowBalloonTip(
                "Lokum notifier working ...",
                $"Status: {_viewModel.Status}, Flats: {_viewModel.FlatsCount}",
                BalloonIcon.Info);
        }

        public async Task UpdateInfo()
        {
            var result = await _webClient.GetFlatInfoAsync();
            await Dispatcher.InvokeAsync(() => // TODO: try without Dispatcher
            {
                _viewModel.UpdateDateTime = DateTime.Now;
                _viewModel.Status = ParseStatus(result.status);

                if (_viewModel.FlatsCount == result.data.count)
                {
                    return;
                }
                _viewModel.FlatsCount = result.data.count;

                var msgResult = MessageBox.Show(
                    this,
                    $"Flat count updated: {_viewModel.FlatsCount}\nOpen LOKUM site?",
                    "Lokum info update",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Exclamation);

                if (msgResult != MessageBoxResult.Yes)
                {
                    return;
                }

                Process.Start(WebClient.NavigationUrl);
            });
        }

        private static string ParseStatus(int status)
        {
            return status > 100 ? 
                ((HttpStatusCode) status).ToString() :
                ((WebExceptionStatus) status).ToString();
        }

        private void ShowHideApp(bool isForceShow)
        {
            if (isForceShow)
            {
                ShowInTaskbar = true;
                Visibility = Visibility.Visible;
                WindowState = WindowState.Normal;
            }
            else
            {
                ShowInTaskbar = !ShowInTaskbar;
                WindowState = ShowInTaskbar ? WindowState.Normal : WindowState.Minimized;
                Visibility = ShowInTaskbar ? Visibility.Visible : Visibility.Hidden;
                ShowNotification();
            }
        }

        private void CloseExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            TimerDispose();
            SystemEvents.SessionSwitch -= OnSessionSwitch;

            Application.Current.Shutdown();
        }

        private void OpenSiteExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            Process.Start(WebClient.NavigationUrl);
        }

        private async void OnTimerElapsed(object sender, ElapsedEventArgs e)
        {
            await UpdateInfo();
        }

        private async void OnSessionSwitch(object sender, SessionSwitchEventArgs e)
        {
            if (e.Reason == SessionSwitchReason.SessionUnlock ||
                e.Reason == SessionSwitchReason.SessionLogon)
            {
                await UpdateInfo();
            }
        }

        private async void UpdateInfoExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            await UpdateInfo();
        }
    }
}